package zbf.com.Entity;

import org.springframework.stereotype.Component;
import zbf.com.utils.myLock;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;

/** 基于LRU实现的 Cache 利用HashMap实现一个双向链表
 * @author 凡
 * @data 2021/6/29
 */

@Component
public class LRU_Cache {
    //双向链表
    private static class Node{
        private String key;
        private Object val;
        private Node prev;
        private Node next;
    }

    private Integer COUNT = 0;
    private static LRU_Cache Cache = new LRU_Cache();
    private final Integer DEF_SIZE = 10;
    private int capacity;
    private Node first;
    private Node last;
    ConcurrentHashMap<String,Node> map;
    Lock lock = new myLock();

    private LRU_Cache(){
        this.capacity = this.DEF_SIZE;
        this.map = new ConcurrentHashMap<>(capacity);
        this.COUNT = 0;
    }
    public static LRU_Cache getInstance(){
        return Cache;
    }

    //移除末尾节点
    public void removeLast(){
        map.remove(last.key);
        Node prevNode = last.prev;
        if(prevNode!=null){
            prevNode.next = null;
            last = prevNode;
        }
    }

    //往头部添加新节点
    public void addToHead(Node node){
        if(map.isEmpty()){
            first = node;
            last = node;
        }else {
            node.next = first;
            first.prev = node;
            first = node;
        }
    }

    //将中间节点移动到头部
    public void moveToHead(Node node){
        if(node == first){
            return;
        }else if(node == last){
            last.prev.next = null;
            last = last.prev;
        }else {
            node.prev.next = node.next;
            node.next.prev = node.prev;
        }
        node.prev = first.prev;
        node.next = first;
        first.prev = node;
        first = node;
    }

    //插入数据
    public void put(String key,Object val){
        this.lock.lock();
        this.COUNT++;
        Node node = this.map.get(key);
        if(node==null){
            node = new Node();
            node.key = key;
            node.val = val;
            if(this.map.size() == capacity)
                removeLast();
            addToHead(node);
            this.map.put(key,node);
        }else{
            node.val = val;
            moveToHead(node);
        }
        this.lock.unlock();
    }

    //清空所有缓存与节点
    public void delAllNode(){
        this.first = null;
        this.last = null;
        this.COUNT = 0;
        this.map.clear();
    }

    @Override
    public String toString(){
        Node node = this.first;
        String s = "COUNT（Cache中PUT的总次数）: "+this.COUNT;
        while (node!=null){
            TestData td = (TestData) node.val;
            s=s+"\n KEY值为："+td.getId();
            node = node.next;
        }
        return s;
    }
}
